﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Findr
{
    /// <summary>
    /// Delegate that updates the contact list
    /// </summary>
    /// <param name="contacts">List of Contact objects</param>
    public delegate void UpdateContactsDelegate(FindrServer.Contact[] contacts);
    /// <summary>
    /// Delegate that updates the message list
    /// </summary>
    /// <param name="messages">List of Message objects</param>
    public delegate void UpdateMessagesDelegate(FindrServer.Message[] messages);

    public class AbsolutePosition
    {
        public double Latitude { get; set; }
        public double Longitude { get; set; }

        public AbsolutePosition(double lat, double lon)
        {
            Latitude = lat;
            Longitude = lon;
        }
    }

    /// <summary>
    /// Class that represents the Contacts module
    /// </summary>
    public class Contacts
    {
        public static NewMarkerDelegate NewMarkerHandler;
        public static MoveMarkerDelegate MoveMarkerHandler;

        public static string ApplicationPath;
        static readonly object sync = new object();

        /// <summary>
        /// Class that represents a message
        /// </summary>
        public class Message
        {
            /// <summary>
            /// Identifier of the message
            /// </summary>
            public int id;
            /// <summary>
            /// Sender (username) of the message
            /// </summary>
            public string sender;
            /// <summary>
            /// Time of sending
            /// </summary>
            public DateTime time;
            /// <summary>
            /// Message body
            /// </summary>
            public string body;
            /// <summary>
            /// Constructor of the Message class
            /// </summary>
            /// <param name="_id">Identifier</param>
            /// <param name="_sender">Sender</param>
            /// <param name="_time">Time</param>
            /// <param name="_body">Body text</param>
            public Message(int _id, string _sender, DateTime _time, string _body)
            {
                id = _id;
                sender = _sender;
                time = _time;
                body = _body;
            }
        }
        /// <summary>
        /// Class that represents a contact
        /// </summary>
        public class Buddy
        {
            private AbsolutePosition pos;
            /// <summary>
            /// Contact identifier
            /// </summary>
            public int id;
            /// <summary>
            /// Marker id
            /// </summary>
            public int marker_id;
            /// <summary>
            /// Contact username
            /// </summary>
            public string name;
            /// <summary>
            /// Last contact activity
            /// </summary>
            public DateTime lastSeen;
            /// <summary>
            /// Last position
            /// </summary>
            public AbsolutePosition Position
            {
                get 
                {
                    return pos;
                }
                set
                {
                    pos = value;
                    MoveMarkerHandler(marker_id, pos.Latitude, pos.Longitude);
                }
            }
            /// <summary>
            /// Twitter name of the contact
            /// </summary>
            public string twitterName;
            /// <summary>
            /// Constructor of the Buddy class
            /// </summary>
            /// <param name="_id">Identifier</param>
            /// <param name="_name">User name</param>
            /// <param name="_lastSeen">Last activity</param>
            /// <param name="_pos">Position</param>
            public Buddy(int _id, string _name, string _lastSeen, AbsolutePosition _pos)
            {
                id = _id;
                name = _name;
                if (_pos == null)
                {
                    lastSeen = DateTime.MinValue;
                    pos = null;
                }
                else
                {
                    lastSeen = DateTime.Parse(_lastSeen);
                    pos = _pos;
                }
                string avatar_file = ApplicationPath + "\\plugins\\Findr\\avatars\\" + name + ".jpg";
                if (System.IO.File.Exists(avatar_file))
                {
                    System.Drawing.Bitmap bmpAvatar = new System.Drawing.Bitmap(avatar_file);
                    marker_id = NewMarkerHandler(Position.Latitude, Position.Longitude, bmpAvatar, null);
                }
                else
                {
                    communicator.GetContactPicture(name);
                    marker_id = NewMarkerHandler(Position.Latitude, Position.Longitude, null, name);
                }
                
            }
        }

        public static Communicator communicator;

        /// <summary>
        /// Array of contacts
        /// </summary>
        public List<Buddy> contactList;
        /// <summary>
        /// Array of messages
        /// </summary>
        public List<Message> messageList;
        /// <summary>
        /// Constuctor of the Contacts class (creates blank structure)
        /// </summary>
        public Contacts(ref Communicator comm)
        {
            contactList = new List<Buddy>();
            messageList = new List<Message>();
            comm.ContactUpdate += UpdateContacts;
            communicator = comm;
        }
        /// <summary>
        /// Returns the given contact's position in the array
        /// </summary>
        /// <param name="_id">Contact identifier</param>
        /// <returns>-1, if the contact was not in the contact list. Otherwise the index of the given contact's position in the array.</returns>
        public int GetBuddyIndex(int _id)
        {
            for (int i = 0; i < contactList.Count; i++)
                if(contactList[i].id == _id)
                    return i;
            return -1;
        }
        /// <summary>
        /// Updates the locally stored contact list
        /// </summary>
        /// <param name="contacts">The actual contact list sent by the server</param>
        public void UpdateContacts(FindrServer.Contact[] contacts)
        {
            try
            {
                foreach (FindrServer.Contact contact in contacts)
                {
                    int id = Convert.ToInt32(contact.id);

                    int currBuddyIndex = GetBuddyIndex(id);
                    // if it's already on the list, update it
                    if (currBuddyIndex >= 0)
                    {
                        lock (sync)
                        {
                            if (contact.latitude != Double.NaN)
                            {
                                contactList[currBuddyIndex].Position.Longitude = contact.longitude;
                                contactList[currBuddyIndex].Position.Latitude = contact.latitude;
                                contactList[currBuddyIndex].lastSeen = DateTime.Parse(contact.last_seen);
                            }
                        }
                    }
                    // if it isn't, create one
                    else
                    {
                        lock (sync)
                        {
                            contactList.Add(new Buddy(id, contact.name, contact.last_seen, new AbsolutePosition(contact.latitude, contact.longitude)));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        /// <summary>
        /// Updates the locally stored messages
        /// </summary>
        /// <param name="messages">Actual message list sent by the server</param>
        public void UpdateMessages(FindrServer.Message[] messages)
        {
            foreach (FindrServer.Message message in messages)
            {
                int i;
                for (i = 0; i < messageList.Count; i++)
                    if (messageList[i].time <= DateTime.Parse(message.time))
                        break;
                messageList.Insert(i, new Message(message.id, message.sender, DateTime.Parse(message.time), message.body));
            }
        }
        /// <summary>
        /// Format messages to a string
        /// </summary>
        /// <returns>String of the messages</returns>
        public string GetMessageString()
        {
            string messageString = "";
            foreach (Message message in messageList)
            {
                messageString += message.sender + "> " + message.body + "\r\n";
            }
            return messageString;
        }
    }
}
